package riven.club.utils;

import com.alibaba.fastjson.JSON;
//import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.BasicHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Map;
import java.util.Objects;

/**
 * HTTP工具类
 *
 * @author maple
 */
public class HttpUtils {

    private static final Logger log = LoggerFactory.getLogger(HttpUtils.class);

    private HttpUtils() {
    }

    /**
     * 将map转换成url
     *
     * @param map 参数
     * @return url
     * @throws UnsupportedEncodingException 编码异常
     */
    public static String getUrlParamsByMap(Map<String, String> map)
            throws UnsupportedEncodingException {
        if (map == null) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<String, String> entry : map.entrySet()) {
            sb.append(entry.getKey()).append("=").append(URLEncoder.encode(entry.getValue(), BaseConstant.CHARSET_UTF8));
            sb.append("&");
        }
        String s = sb.toString();
        if (s.endsWith("&")) {
            s = StringUtils.substringBeforeLast(s, "&");
        }
        return s;
    }

    /**
     * 连接发送服务器的时间,3秒
     */
    private static final int CONNECT_TIMEOUT = 60 * 1000;
    /**
     * 等待发送服务器返回的时间,假设通道商最慢也能在60分钟之内返回
     */
    private static final int READ_TIMEOUT = 60 * 1000;


    public static String sendHandleGet(String url, Map<String, String> params, Map<String, String> headers) throws IOException {
        String responseBody = null;
        //重试机制可能需要改善
        String paramString = getUrlParamsByMap(params);
        if (StringUtils.isNotEmpty(paramString)) {
            url = url + "?" + paramString;
        }
        HttpGet httpGet = new HttpGet(url);
        buildBaseHttpRequest(httpGet, headers);
        CloseableHttpResponse response = null;
        CloseableHttpClient httpClient = HttpClients.createDefault();
        try {
            long t1 = System.currentTimeMillis();
            log.info("[{}],HTTP请求[{}],header[{}]", url, BaseConstant.GET, headers);
            response = httpClient.execute(httpGet);
            int statusCode = response.getStatusLine().getStatusCode();
            HttpEntity entity = response.getEntity();
            responseBody = EntityUtils.toString(entity, BaseConstant.CHARSET_UTF8);
            long t2 = System.currentTimeMillis();
            log.info("[{}],HTTP请求[{}],code[{}],返回结果[{}],响应时间:[{}]", url, statusCode, BaseConstant.GET, responseBody, t2 - t1);
        } catch (Exception e) {
            log.error("[{}]发送流程异常", url, e);
        } finally {
            if (response != null) {
                response.close();
            }
            httpClient.close();
        }
        return responseBody;
    }

    public static void buildBaseHttpRequest(HttpRequestBase httpRequest, Map<String, String> headers) {
        httpRequest.setConfig(RequestConfig.custom().setConnectTimeout(CONNECT_TIMEOUT).setSocketTimeout(READ_TIMEOUT).build());
        httpRequest.setHeader("Accept", "application/json;charset=utf-8");
        httpRequest.setHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");
        if (headers != null) {
            for (Map.Entry<String, String> header : headers.entrySet()) {
                httpRequest.setHeader(header.getKey(), header.getValue());
            }
        }
    }

    /**
     * post发送的接口
     *
     * @param url     URL地址
     * @param body    postBody
     * @param params  url参数
     * @param headers http Header参数
     * @return 返回结果字符串
     * @throws IOException 网络请求错误
     */
    public static String sendHandlePost(String url, String body, Map<String, String> params, Map<String, String> headers) throws IOException {
        return sendHandlePost(url, body, params, headers, (HttpEntity) null);
    }

    /**
     * post发送的接口
     *
     * @param url     URL地址
     * @param body    postBody
     * @param params  url参数
     * @param headers http Header参数
     * @return 返回结果字符串
     * @throws IOException 网络请求错误
     */
    public static String sendHandlePost(String url, String body, Map<String, String> params, Map<String, String> headers, HttpEntity httpEntity) throws IOException {
        String responseBody = null;
        //重试机制可能需要改善
        String paramString = getUrlParamsByMap(params);
        if (StringUtils.isNotEmpty(paramString)) {
            url = url + "?" + paramString;
        }
        HttpPost post = new HttpPost(url);
        buildBaseHttpRequest(post, headers);
        if (null != httpEntity) {
            post.setEntity(httpEntity);
        } else {
            StringEntity codeEntity = new StringEntity(body, ContentType.APPLICATION_JSON);
            post.setEntity(codeEntity);
        }
        CloseableHttpResponse response = null;
        CloseableHttpClient httpClient = HttpClients.createDefault();
        try {
            long t1 = System.currentTimeMillis();
            log.info("[{}],HTTP请求[{}],header[{}],body[{}]", url, BaseConstant.POST, headers, body);
            response = httpClient.execute(post);
            int statusCode = response.getStatusLine().getStatusCode();
            HttpEntity entity = response.getEntity();
            responseBody = EntityUtils.toString(entity, BaseConstant.CHARSET_UTF8);
            long t2 = System.currentTimeMillis();
            log.info("[{}],HTTP请求[{}],code[{}],返回结果[{}],响应时间:[{}]", url, statusCode, BaseConstant.POST, responseBody, t2 - t1);
        } catch (Exception e) {
            log.error("[{}]发送流程异常", url, e);
        } finally {
            if (response != null) {
                response.close();
            }
            httpClient.close();
        }
        return responseBody;
    }

    /**
     * post发送的接口
     *
     * @param url                        URL地址
     * @param body                       postBody
     * @param params                     url参数
     * @param headers                    http Header参数
     * @param sslConnectionSocketFactory 证书
     * @return 返回结果字符串
     * @throws IOException 网络请求错误
     */
    public static String sendHandlePost(String url, String body, Map<String, String> params, Map<String, String> headers, SSLConnectionSocketFactory sslConnectionSocketFactory) throws IOException {
        BasicHttpClientConnectionManager connManager = new BasicHttpClientConnectionManager(
                RegistryBuilder.<ConnectionSocketFactory>create()
                        .register("http", PlainConnectionSocketFactory.getSocketFactory())
                        .register("https", sslConnectionSocketFactory)
                        .build(),
                null,
                null,
                null
        );
        //重试机制可能需要改善
        String paramString = getUrlParamsByMap(params);
        if (StringUtils.isNotEmpty(paramString)) {
            url = url + "?" + paramString;
        }
        HttpClient httpClient = HttpClientBuilder.create()
                .setConnectionManager(connManager)
                .build();
        HttpPost post = new HttpPost(url);
        buildBaseHttpRequest(post, headers);
        StringEntity codeEntity = new StringEntity(body, ContentType.APPLICATION_JSON);
        post.setEntity(codeEntity);
        long t1 = System.currentTimeMillis();
        post.setEntity(codeEntity);
        log.info("[{}],HTTP请求[{}],header[{}],body[{}]", url, BaseConstant.POST, headers, body);
        HttpResponse httpResponse = httpClient.execute(post);
        int statusCode = httpResponse.getStatusLine().getStatusCode();
        HttpEntity entity = httpResponse.getEntity();
        String responseBody = EntityUtils.toString(entity, BaseConstant.CHARSET_UTF8);
        long t2 = System.currentTimeMillis();
        log.info("[{}],HTTP请求[{}],code[{}],返回结果[{}],响应时间:[{}]", url, statusCode, BaseConstant.POST, responseBody, t2 - t1);
        return responseBody;
    }

//    /**
//     * 微信资源请求
//     *
//     * @param url     URL地址
//     * @param params  参数
//     * @param headers 请求头
//     * @param clazz   返回类型
//     * @return 返回结果
//     * @throws IOException 异常
//     */
//    public static <T extends WxStreamResponse> T sendWxStreamHandleGet(String url, Map<String, String> params, Map<String, String> headers, Class<T> clazz) throws IOException {
//        T result = null;
//        //重试机制可能需要改善
//        String paramString = getUrlParamsByMap(params);
//        if (StringUtils.isNotEmpty(paramString)) {
//            url = url + "?" + paramString;
//        }
//        HttpGet httpGet = new HttpGet(url);
//        buildBaseHttpRequest(httpGet, headers);
//        long t1 = System.currentTimeMillis();
//        log.info("[{}],HTTP请求[{}],header[{}]", url, BaseConstant.GET, headers);
//        try (CloseableHttpClient httpClient = HttpClients.createDefault();
//             CloseableHttpResponse response = httpClient.execute(httpGet)) {
//            int statusCode = response.getStatusLine().getStatusCode();
//            HttpEntity entity = response.getEntity();
//            String contentType = Objects.isNull(entity.getContentType()) ? null : entity.getContentType().getValue();
//            if (StringUtils.isNotEmpty(contentType) && (contentType.contains(ContentType.APPLICATION_JSON.getMimeType()) || contentType.contains(ContentType.TEXT_PLAIN.getMimeType()))) {
//                result = JSON.parseObject(EntityUtils.toString(entity, BaseConstant.CHARSET_UTF8), clazz);
//                long t2 = System.currentTimeMillis();
//                log.info("[{}],HTTP请求[{}],code[{}],返回结果[{}],响应时间:[{}]", url, statusCode, BaseConstant.GET, result, t2 - t1);
//            } else {
//                result = clazz.newInstance();
//                result.setStream(IOUtils.toByteArray(entity.getContent()));
//                long t2 = System.currentTimeMillis();
//                log.info("[{}],HTTP请求[{}],code[{}],响应时间:[{}]", url, statusCode, BaseConstant.GET, t2 - t1);
//            }
//        } catch (Exception e) {
//            log.error("[{}]发送流程异常", url, e);
//        }
//        return result;
//    }
//
//    /**
//     * 微信资源请求
//     *
//     * @param url     URL地址
//     * @param params  参数
//     * @param headers 请求头
//     * @return 返回结果
//     * @throws IOException 异常
//     */
//    public static <T extends WxStreamResponse> T sendWxStreamHandlePost(String url, String body, Map<String, String> params, Map<String, String> headers, Class<T> clazz) throws IOException {
//        T result = null;
//        //重试机制可能需要改善
//        String paramString = getUrlParamsByMap(params);
//        if (StringUtils.isNotEmpty(paramString)) {
//            url = url + "?" + paramString;
//        }
//        HttpPost post = new HttpPost(url);
//        buildBaseHttpRequest(post, headers);
//        StringEntity codeEntity = new StringEntity(body, ContentType.APPLICATION_JSON);
//        post.setEntity(codeEntity);
//        long t1 = System.currentTimeMillis();
//        log.info("[{}],HTTP请求[{}],header[{}],body[{}]", url, BaseConstant.POST, headers, body);
//        try (CloseableHttpClient httpClient = HttpClients.createDefault();
//             CloseableHttpResponse response = httpClient.execute(post)) {
//            int statusCode = response.getStatusLine().getStatusCode();
//            HttpEntity entity = response.getEntity();
//            String contentType = Objects.isNull(entity.getContentType()) ? null : entity.getContentType().getValue();
//            if (StringUtils.isNotEmpty(contentType) && (contentType.contains(ContentType.APPLICATION_JSON.getMimeType()) || contentType.contains(ContentType.TEXT_PLAIN.getMimeType()))) {
//                result = JSON.parseObject(EntityUtils.toString(entity, BaseConstant.CHARSET_UTF8), clazz);
//                long t2 = System.currentTimeMillis();
//                log.info("[{}],HTTP请求[{}],code[{}],返回结果[{}],响应时间:[{}]", url, statusCode, BaseConstant.POST, result, t2 - t1);
//            } else {
//                result = clazz.newInstance();
//                result.setStream(IOUtils.toByteArray(entity.getContent()));
//                long t2 = System.currentTimeMillis();
//                log.info("[{}],HTTP请求[{}],code[{}],响应时间:[{}]", url, statusCode, BaseConstant.POST, t2 - t1);
//            }
//        } catch (Exception e) {
//            log.error("[{}]发送流程异常", url, e);
//        }
//        return result;
//    }
}
